# ifndef PACKAGE_H
# define PACKAGE_H

# include <string>

# include <autosprintf.h>

# include <misc.H>
# include <grid.H>

class Grid;

class Grid_Node;

/**
  * \brief Modela un paquete que se mueve por la red.
  * @authors Alejandro Mujica, Anna Lezama
  */
class Package
{
  unsigned long id;      // Identificador unico de cada paquete
  unsigned short ttl;    // Tiempo de vida de un paquete, por cuantos enlaces ha pasado
  unsigned short tiq;
  Grid_Node * source;    // Direccion del nodo que envia el paquete
  Grid_Node * target;    // Direccion del destino del paquete
  Grid_Node * routed_to; // Hacia donde se ha enrutado el paquete en un instante de tiempo

  Direction h_favorable_direction; // Direccion favorable horizontal
  Direction v_favorable_direction; // Direccion favorable vertical

  unsigned long num_deflections; // Contador de deflecciones del paquete
  unsigned long num_routings;    // Contador de enrutamientos correctos

  bool __is_in_queue;  // Indica si se encuentra en cola
  bool __is_deliveried; // Indica si ya ha sido entregado

public:
  Package();

  Package(const unsigned long & _id, Grid_Node * src, Grid_Node * tgt);

  Package(const Package & p);

  ~Package();

  const unsigned long & get_id() const;

  /**
    * Retorna el tiempo (cantidad de iteraciones) que ha pasado un nodo movi&eacute;ndose en la red.
    */
  const unsigned short & get_ttl() const;

  /**
    * Retorna el tiempo (cantidad de iteraciones) que ha pasado un nodo movi&eacute;ndose en cola de entrada de un nodo.
    */
  const unsigned short & get_tiq() const;

  /**
    * Incrementa el n&uacute;mero de iteraciones de un paquete en la red.
    */
  void inc_ttl();

  /**
    * Incrementa el n&uacute;mero de iteraciones de un paquete en cola de entrada de un nodo.
    */
  void inc_tiq();

  /**
    * Incrementa el n&uacute;mero de deflecciones que se le han hecho al paquete.
    */
  void inc_num_deflections();

  /**
    * Incrementa el n&uacute;mero de enrutamientos favorables que se le han hecho al paquete.
    */
  void inc_num_routings();

  /**
    * Retorna el nodo desde el cual fue enviado.
    */
  Grid_Node * get_source_node();

  /**
    * Retorna el nodo hacia el cual se dirige el paquete (destino final en la red).
    */
  Grid_Node * get_target_node();

  /**
    * Retorna el nodo al que ha sido enrutado un paquete en un momento dado.
    */
  Grid_Node * get_routed_to();

  /**
    * Retorna el n&uacute;mero de deflecciones que se le han hecho al paquete en un momento.
    */
  const unsigned long & get_num_deflections();

  /**
    * Retorna el n&uacute;mero de enrutamientos favorables que se le han hecho al paquete en un momento.
    */
  const unsigned long & get_num_routings();

  bool & is_in_queue();

  bool & is_deliveried();

  /**
    * Retorna el n&uacute;mero de direcciones favorables de un paquete en un momento dado.
    */
  const unsigned short get_num_favorable_directions() const;

  void reset();

  void rout_to(Grid_Node * node);

  /**
    * Retorna la direcci&oacute;n favorable horizontal del nodo (constante).
    */
  const Direction & get_h_favorable_direction() const;

  /**
    * Retorna la direcci&oacute;n favorable horizontal del nodo (modificable).
    */
  Direction & get_h_favorable_direction();

  /**
    * Retorna la direcci&oacute;n favorable vertical del nodo (constante).
    */
  const Direction & get_v_favorable_direction() const;

  /**
    * Retorna la direcci&oacute;n favorable vertical del nodo (modificable).
    */
  Direction & get_v_favorable_direction();


  /**
    * Retorna la direcci&oacute;n pasada como parámetro.
    */
  const Direction get_favorable_direction(Direction) const;


  /**
    * Retorna una descripci&oacute;n del paquete,
    * en este caso es la palabra Paquete con el n&uacute;mero que lo identifica.
    */
  const std::string to_string();
};

# endif
